%     FASTENER DOCTOR - программа для лечения и конвертации крепежа
%     Copyright (C) 2018  Михаил Козлов
%     Сайт проекта: <http://www.fastenerdoctor.ru/>
%     Адрес электронной почты для связи с разработчиком:
%     <doctor.fastener@gmail.com>
% 
%     Эта программа является свободным программным обеспечением: Вы можете
%     распространять ее и/или изменять, соблюдая условия Универсальной общественной
%     лицензии GNU, опубликованной Фондом свободного программного обеспечения,
%     либо редакции 3, либо (на Ваше усмотрение) любой редакции, выпущенной позже.
% 
%     Эта программа распространяется в надежде на то, что она окажется полезной,
%     но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, включая даже подразумеваемую гарантию ТОВАРНОЙ ПРИГОДНОСТИ,
%     либо ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Ознакомьтесь с Универсальной общественной
%     лицензией GNU для получения более подробной информации.
% 
%     Вы должны были получить копию Универсальной общественной лицензии GNU
%     вместе с этой программой. Если Вы ее не получили, то перейдите по адресу:
%     <http://www.gnu.org/licenses/>.
% 
%     This program is free software: you can redistribute it and/or modify
%     it under the terms of the GNU General Public License as published by
%     the Free Software Foundation, either version 3 of the License, or
%     (at your option) any later version.
% 
%     This program is distributed in the hope that it will be useful,
%     but WITHOUT ANY WARRANTY; without even the implied warranty of
%     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%     GNU General Public License for more details.
% 
%     You should have received a copy of the GNU General Public License
%     along with this program.  If not, see <https://www.gnu.org/licenses/>.

function NODES = Read_NODES(Fin, N_Nodes, Node_start_position)

% NODES (карточка GRID) | .ID | .Ref_Location(3,1) | .Location(3,1) | .Reference_CID | .Analysis_CID |

global ErrCode;
global Progress_Bar_Segments;
global Progress_Bar_Delay;

fprintf (1, '    Чтение узлов...                     ');

NODES = cell(N_Nodes,1);

fseek(Fin, Node_start_position, 'bof');

Node_read_counter = 0;


% Для вывода прогресса
Time_segments = Progress_Bar_Segments;
N_records = N_Nodes;
N_rec_segm = floor(N_records/Time_segments);
Counter = 0;
Counter_2 = 0;
Written_count = 0;


while (~feof(Fin))
    
    if (Node_read_counter == N_Nodes)
        break;        
    end
    
    string = fgets(Fin);
    
    if (string(1) == 'G')
        
        % Чтение GRID
        
        if ((length(string) >= 5) && strcmp(string(2:5), 'RID ')) % SMALL FIELD FORMAT

            Node_read_counter = Node_read_counter + 1;
            
            NODES{Node_read_counter}.ID = [];
            NODES{Node_read_counter}.Ref_Location = zeros(3,1);
            NODES{Node_read_counter}.Location = zeros(3,1);
            NODES{Node_read_counter}.Reference_CID = 0;
            NODES{Node_read_counter}.Analysis_CID = 0;

            % Чтение ID
            tmp_number = str2double(string(9:16));
            if (isnan(tmp_number))
                fprintf (1, '\nНеправильная запись с номером узла в карточке GRID : [%s] !\n', strtrim(string(9:16)));
                ErrCode = -1;
                return;
            end
            NODES{Node_read_counter}.ID = tmp_number;

            % Чтение Reference CID
            if (~isnan(str2double(string(17:24))))
                NODES{Node_read_counter}.Reference_CID = str2double(string(17:24));
            end

            % Чтение X
            tmp_number = str2double(string(25:32));
            if (isnan(tmp_number))
                tmp_number_2 = sscanf(string(25:32), '%e%d');
                if (size(tmp_number_2,1) ~= 2)
                    fprintf (1, '\nНеправильная запись с координатой X в карточке GRID узла %i : [%s] !\n', NODES{Node_read_counter}.ID, strtrim(string(25:32)));
                    ErrCode = -1;
                    return;
                end
                NODES{Node_read_counter}.Ref_Location(1) = tmp_number_2(1)*10^tmp_number_2(2);
            else
                NODES{Node_read_counter}.Ref_Location(1) = tmp_number;
            end

            % Чтение Y
            tmp_number = str2double(string(33:40));
            if (isnan(tmp_number))
                tmp_number_2 = sscanf(string(33:40), '%e%d');
                if (size(tmp_number_2,1) ~= 2)
                    fprintf (1, '\nНеправильная запись с координатой Y в карточке GRID узла %i : [%s] !\n', NODES{Node_read_counter}.ID, strtrim(string(33:40)));
                    ErrCode = -1;
                    return;
                end
                NODES{Node_read_counter}.Ref_Location(2) = tmp_number_2(1)*10^tmp_number_2(2);
            else
                NODES{Node_read_counter}.Ref_Location(2) = tmp_number;
            end

            % Чтение Z
            if (length(string) < 48)
                End_index = length(string);
            else
                End_index = 48;
            end
            tmp_number = str2double(string(41:End_index));
            if (isnan(tmp_number))
                tmp_number_2 = sscanf(string(41:End_index), '%e%d');
                if (size(tmp_number_2,1) ~= 2)
                    fprintf (1, '\nНеправильная запись с координатой Z в карточке GRID узла %i : [%s] !\n', NODES{Node_read_counter}.ID, strtrim(string(41:End_index)));
                    ErrCode = -1;
                    return;
                end
                NODES{Node_read_counter}.Ref_Location(3) = tmp_number_2(1)*10^tmp_number_2(2);
            else
                NODES{Node_read_counter}.Ref_Location(3) = tmp_number;
            end

            % Чтение Analysis CID
            if (length(Trim_CR_LF(string)) > 48)
                if (length(string) < 56)
                    End_index = length(string);
                else
                    End_index = 56;
                end
                if (~isnan(str2double(string(49:End_index))))
                    NODES{Node_read_counter}.Analysis_CID = str2double(string(49:End_index));
                end
            end

            
            % Для вывода прогресса
            Counter = Counter + 1;
            Counter_2 = Counter_2 + 1;
            if (Counter_2 == N_rec_segm)
                Counter_2 = 0;
                Written_count = Written_count + 1;
                if (Written_count < Time_segments)
                    fprintf (1, '#');
                    pause (Progress_Bar_Delay);
                end
            end
            
            
            continue;

        end
        
        if ((length(string) >= 5) && strcmp(string(2:5), 'RID*')) % LARGE FIELD FORMAT

            Node_read_counter = Node_read_counter + 1;
            
            NODES{Node_read_counter}.ID = [];
            NODES{Node_read_counter}.Ref_Location = zeros(3,1);
            NODES{Node_read_counter}.Location = zeros(3,1);
            NODES{Node_read_counter}.Reference_CID = 0;
            NODES{Node_read_counter}.Analysis_CID = 0;

            % Чтение ID
            tmp_number = str2double(string(9:24));
            if (isnan(tmp_number))
                fprintf (1, '\nНеправильная запись с номером узла в карточке GRID* : [%s] !\n', strtrim(string(9:24)));
                ErrCode = -1;
                return;
            end
            NODES{Node_read_counter}.ID = tmp_number;

            % Чтение Reference CID
            if (~isnan(str2double(string(25:40))))
                NODES{Node_read_counter}.Reference_CID = str2double(string(25:40));
            end

            % Чтение X
            tmp_number = str2double(string(41:56));
            if (isnan(tmp_number))
                tmp_number_2 = sscanf(string(41:56), '%e%d');
                if (size(tmp_number_2,1) ~= 2)
                    fprintf (1, '\nНеправильная запись с координатой X в карточке GRID* узла %i : [%s] !\n', NODES{Node_read_counter}.ID, strtrim(string(41:56)));
                    ErrCode = -1;
                    return;
                end
                NODES{Node_read_counter}.Ref_Location(1) = tmp_number_2(1)*10^tmp_number_2(2);
            else
                NODES{Node_read_counter}.Ref_Location(1) = tmp_number;
            end

            % Чтение Y
            if (length(string) < 72)
                End_index = length(string);
            else
                End_index = 72;
            end
            tmp_number = str2double(string(57:End_index));
            if (isnan(tmp_number))
                tmp_number_2 = sscanf(string(57:End_index), '%e%d');
                if (size(tmp_number_2,1) ~= 2)
                    fprintf (1, '\nНеправильная запись с координатой Y в карточке GRID* узла %i : [%s] !\n', NODES{Node_read_counter}.ID, strtrim(string(57:End_index)));
                    ErrCode = -1;
                    return;
                end
                NODES{Node_read_counter}.Ref_Location(2) = tmp_number_2(1)*10^tmp_number_2(2);
            else
                NODES{Node_read_counter}.Ref_Location(2) = tmp_number;
            end
            
            % Проверка на конец файла
            if (feof(Fin))
                fprintf (1, '\nНеожиданный конец файла во время чтения карточки GRID* с номером %i !\n', NODES{Node_read_counter}.ID);
                ErrCode = -1;
                return;
            end

            % Чтение следующей строки
            string = fgets(Fin);

            % Проверка строки
            if (~(string(1) == '*'))
                fprintf (1, '\nВторая строка в карточке GRID* узла %i не начинается с символа * !\n', NODES{Node_read_counter}.ID);
                ErrCode = -1;
                return;
            end

            % Чтение Z
            if (length(string) < 24)
                End_index = length(string);
            else
                End_index = 24;
            end
            tmp_number = str2double(string(9:End_index));
            if (isnan(tmp_number))
                tmp_number_2 = sscanf(string(9:End_index), '%e%d');
                if (size(tmp_number_2,1) ~= 2)
                    fprintf (1, '\nНеправильная запись с координатой Z в карточке GRID* узла %i : [%s] !\n', NODES{Node_read_counter}.ID, strtrim(string(9:End_index)));
                    ErrCode = -1;
                    return;
                end
                NODES{Node_read_counter}.Ref_Location(3) = tmp_number_2(1)*10^tmp_number_2(2);
            else
                NODES{Node_read_counter}.Ref_Location(3) = tmp_number;
            end

            % Чтение Analysis CID
            if (length(Trim_CR_LF(string)) > 24)
                if (length(string) < 40)
                    End_index = length(string);
                else
                    End_index = 40;
                end
                if (~isnan(str2double(string(25:End_index))))
                    NODES{Node_read_counter}.Analysis_CID = str2double(string(25:End_index));
                end
            end
                
            
            % Для вывода прогресса
            Counter = Counter + 1;
            Counter_2 = Counter_2 + 1;
            if (Counter_2 == N_rec_segm)
                Counter_2 = 0;
                Written_count = Written_count + 1;
                if (Written_count < Time_segments)
                    fprintf (1, '#');
                    pause (Progress_Bar_Delay);
                end
            end
            
            continue;

        end
        
        if ((length(string) >= 5) && strcmp(string(2:5), 'RID,')) % FREE FIELD FORMAT
            
            fprintf (1, '\nОшибка функции Read_NODES: FREE FIELD FORMAT файла bdf не поддерживается в текущей версии программы [GRID,] !\n');
            ErrCode = -1;
            return; 
            
        end
        
    end

end


% Для вывода прогресса
if (N_rec_segm == 0)
    for i=1:Time_segments-1
        fprintf (1, '#');
        pause (Progress_Bar_Delay);
    end
end
fprintf (1, '# ');
pause (Progress_Bar_Delay);


% Обработка исключений
if (Node_read_counter < N_Nodes)
    fprintf (1, '\nОшибка функции Read_NODES: Node_read_counter < N_Nodes !\n');
    ErrCode = -1;
    return;        
end

fprintf (1, 'OK!\n');
